import { renderSlot } from 'vue';
import { Subject, Unsubscribable } from 'rxjs';
import { FormItemController, IParam, IViewStateParam } from 'ibz-core';
import { ComponentBase, GenerateComponent } from '../../component-base';

/**
 * 表单项输入参数
 *
 * @class AppFormItemProps
 */
class AppFormItemProps {
  /**
   * 表单数据项控制器
   *
   * @type {FormButtonController}
   * @memberof AppFormItemProps
   */
  c: IParam = {};

  /**
   * @description 部件name
   * @type {string}
   * @memberof AppFormItemProps
   */
  name: string = '';

  /**
   * @description 表单数据
   * @type {IParam}
   * @memberof AppFormItemProps
   */
  data: IParam = {};

  /**
   * @description 表单状态
   * @type {(Subject<IViewStateParam> | null)}
   * @memberof AppFormItemProps
   */
  formState: Subject<IViewStateParam> | null = null;

  /**
   * 模型服务
   *
   * @type {IParam}
   * @memberof AppFormItemProps
   */
  modelService: IParam = {};
}

/**
 * 表单项
 *
 * @class AppFormItem
 */
export default class AppFormItem extends ComponentBase<AppFormItemProps> {
  /**
   * @description 表单按钮控制器实例对象
   * @type {FormButtonController}
   * @memberof AppFormItem
   */
  public c!: FormItemController;

  /**
   * @description 部件name
   * @type {string}
   * @memberof AppFormItem
   */
  public name: string = '';

  /**
   * @description 表单状态
   * @type {Subject<IViewStateParam>}
   * @memberof AppFormItem
   */
  public formState: Subject<IViewStateParam> = new Subject();

  /**
   * @description 表单事件
   * @type {(Unsubscribable | undefined)}
   * @memberof AppFormItem
   */
  public formStateEvent: Unsubscribable | undefined;

  /**
   * @description 表单旧数据
   * @type {IParam}
   * @memberof AppFormItem
   */
  public oldFormData: IParam = {};

  /**
   * @description 表单数据
   * @type {IParam}
   * @memberof AppFormItem
   */
  public data: IParam = {};

  /**
   * @description 设置响应式
   * @memberof AppFormItem
   */
  setup() {
    this.c = this.props.c as FormItemController;
    this.name = this.props.name;
  }

  /**
   * @description 初始化
   * @memberof AppFormItem
   */
  init() {
    this.c.initInputData(this.props);
  }

  /**
   * @description 无标签
   * @memberof AppFormItem
   */
  public renderNoneLabel() {
    const editor = this.c.model.getPSEditor();
    const editorStyle = {
      width: editor?.editorWidth ? `${editor.editorWidth}px` : '',
      height: editor?.editorHeight ? `${editor.editorHeight}px` : '',
    };
    return [
      <div class={`${this.name}-item-content`}>
        <div class={`${this.name}-item-editor`} style={editorStyle}>
          {renderSlot(this.ctx.slots, 'default')}
        </div>
        <div class={`${this.name}-item-error`}> {this.c.error} </div>
      </div>,
    ];
  }

  /**
   * @description 标签位于下方
   * @memberof AppFormItem
   */
  public renderBottomLabel() {
    return this.renderLeftLabel();
  }

  /**
   * @description 标签位于上方
   * @memberof AppFormItem
   */
  public renderTopLabel() {
    const { showCaption, labelWidth, emptyCaption, caption } = this.c.model;
    const labelClass = this.c.model.getLabelPSSysCss()?.cssName;
    const editor = this.c.model.getPSEditor();
    const editorStyle = {
      width: editor?.editorWidth ? `${editor.editorWidth}px` : '',
      height: editor?.editorHeight ? `${editor.editorHeight}px` : '',
    };
    return [
      showCaption ? (
        <ion-label position='stacked' style={{ width: `${labelWidth}px` }} class={['form-item-label', labelClass]}>
          {this.c.required ? <span class='required'>* </span> : null}
          {emptyCaption ? '' : this.$tl(this.c.model?.getCapPSLanguageRes()?.lanResTag, caption)}
        </ion-label>
      ) : null,
      <div class={`${this.name}-item-content`}>
        <div class={`${this.name}-item-editor`} style={editorStyle}>
          {renderSlot(this.ctx.slots, 'default')}
        </div>
        <div class={`${this.name}-item-error`}> {this.c.error} </div>
      </div>,
    ];
  }

  /**
   * @description 标签位于右侧
   * @memberof AppFormItem
   */
  public renderRightLabel() {
    return this.renderLeftLabel();
  }

  /**
   * @description 标签位于左侧
   * @memberof AppFormItem
   */
  public renderLeftLabel() {
    const { showCaption, labelWidth, emptyCaption, caption } = this.c.model;
    const labelClass = this.c.model.getLabelPSSysCss()?.cssName;
    const editor = this.c.model.getPSEditor();
    const editorStyle = {
      width: editor?.editorWidth ? `${editor.editorWidth}px` : '',
      height: editor?.editorHeight ? `${editor.editorHeight}px` : '',
    };
    return [
      showCaption ? (
        <ion-label position='fixed' style={{ width: `${labelWidth}px` }} class={['form-item-label', labelClass]}>
          {this.c.required ? <span class='required'>* </span> : null}
          {emptyCaption ? '' : this.$tl(this.c.model?.getCapPSLanguageRes()?.lanResTag, caption)}
        </ion-label>
      ) : null,
      <div class={`${this.name}-item-content`}>
        <div class={`${this.name}-item-editor`} style={editorStyle}>
          {renderSlot(this.ctx.slots, 'default')}
        </div>
        <div class={`${this.name}-item-error`}> {this.c.error} </div>
      </div>,
    ];
  }

  /**
   * @description 根据标签位置渲染
   * @memberof AppFormItem
   */
  public renderContentByLabelPos() {
    const labelPos = this.c.model.labelPos;
    switch (labelPos) {
      case 'BOTTOM':
        return this.renderBottomLabel();
      case 'LEFT':
        return this.renderLeftLabel();
      case 'NONE':
        return this.renderNoneLabel();
      case 'RIGHT':
        return this.renderRightLabel();
      case 'TOP':
        return this.renderTopLabel();
    }
  }

  /**
   * @description 渲染表单项
   * @returns {JSX.Element | JSX.Element[] | null}
   * @memberof AppFormItem
   */
  render(): JSX.Element | JSX.Element[] | null {
    return <ion-item class={`${this.name}-item`}>{this.renderContentByLabelPos()}</ion-item>;
  }
}

//  表单项组件
export const AppFormItemComponent = GenerateComponent(AppFormItem, Object.keys(new AppFormItemProps()));
